#!/usr/bin/python3.9
# -*- coding: utf-8 -*-
# @Time    : 2021/10/8 15:12
# @Author  : YHSimon
# 多变量线性回归

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt



def computeCost(X, y, theta):
    inner = np.power(((X * theta.T) - y), 2)
    return np.sum(inner) / (2 * len(X))


def gradientDescent(X, y, theta, alpha, epoch):
    """return theta,cost"""

    tmp = np.matrix(np.zeros(theta.shape))
    parameters = int(theta.flatten().shape[1])  # 参数θ的数量
    cost = np.zeros(epoch)  # 初始化一个ndarray，包含每次epoch的cost
    m = X.shape[0]  # 样本数量m

    for i in range(epoch):
        # 利用向量化一步求解
        tmp = theta - (alpha / m) * (X * theta.T - y).T * X

        # 以下是不用Vectorization求解梯度下降
        #         error = (X * theta.T) - y  # (97, 1)

        #         for j in range(parameters):
        #             term = np.multiply(error, X[:,j])  # (97, 1)
        #             temp[0,j] = theta[0,j] - ((alpha / m) * np.sum(term))  # (1,1)
        theta = tmp
        cost[i] = computeCost(X, y, theta)
    return theta, cost


if __name__ == '__main__':
    path = 'ex1data2.txt'
    data2 = pd.read_csv(path, names=['Size', 'Bedrooms', 'Price'])
    print(data2.head())
    # 特征归一化
    data2 = (data2 - data2.mean()) / data2.std()
    print(data2.head())

    # add ones column
    data2.insert(0, 'Ones', 1)

    # set X(training data) and y(target variable)
    cols = data2.shape[1]
    X2 = data2.iloc[:, 0:cols - 1]
    y2 = data2.iloc[:, cols - 1:cols]

    # convert to matrices and initialize theta
    X2 = np.matrix(X2.values)
    y2 = np.matrix(y2.values)
    theta2 = np.matrix(np.array([0, 0, 0]))

    alpha = 0.01
    epoch = 1000
    # perform linear regression on the data set
    g2, cost2 = gradientDescent(X2, y2, theta2, alpha, epoch)
    """
    fig, ax = plt.subplots(figsize=(12, 8))
    ax.plot(np.arange(epoch), cost2, 'r')
    ax.set_xlabel('Iterations')
    ax.set_ylabel('Cost')
    ax.set_title('Error vs. Training Epoch')
    plt.show()

    # get the cost (error) of the model
    computeCost(X2, y2, g2)
    """

